Навигация. Передача данных. TextField
➡️Ссылка на репозиторий с кодом этого урока
Возвращение данных на предыдущий экран
В Flutter существует несколько способов передать данные обратно на предыдущий экран при навигации. Самый простой и распространенный способ — вернуть данные через Navigator.pop()

Файл first_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_navigation/screens/second_screen.dart';
import 'package:flutter_navigation/screens/user.dart';
class FirstScreen extends StatefulWidget {
static const routeName = '/first';
const FirstScreen({super.key});
@override
State<FirstScreen> createState() => _FirstScreenState();
}
class _FirstScreenState extends State<FirstScreen> {
TextEditingController textController = TextEditingController();
@override
Widget build(BuildContext context) {
final data = ModalRoute.of(context)?.settings.arguments as UserProfile;
return Scaffold(
appBar: AppBar(
title: const Text('Первый экран'),
backgroundColor: Colors.green[300],
),
body: Container(
decoration: BoxDecoration(
gradient: LinearGradient(
colors: [Color(0xFFBFF098), Color(0xFF6FD6FF)],
begin: Alignment.topLeft,
end: Alignment.bottomRight,
),
),
child: SizedBox(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Text(data.name ?? ''),
Padding(
padding: const EdgeInsets.all(24.0),
child: TextField(
controller: textController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Введите сообщение',
),
),
),
ElevatedButton(
onPressed:
() => Navigator.pushNamed(
context,
SecondScreen.routeName,
arguments: UserProfile(
name: data.name,
message: textController.text,
),
),
child: const Text("Открыть 2й экран"),
),
ElevatedButton(
onPressed: () => Navigator.pop(
context,
"Ты был на 1 экране!
Я запомнил твое имя: ${data.name}"
),
child: const Text("Вернуться Назад"),
),
],
),
),
),
);
}
}
В код экрана мы добавили в обработчик нажатия кнопки Вернуться Назад этот код:
ElevatedButton(
onPressed: () => Navigator.pop(
context,
"Ты был на 1 экране! Я запомнил твое имя: ${data.name}"
),
child: const Text("Вернуться Назад"),
),
Через pop() можно вернуть любой тип данных:
- Примитивы (
String,int,bool) - Списки и словари (
List,Map) - Пользовательские объекты (свои
классы) Null(если ничего не передать в pop)
Теперь чтобы принять значения на экране MainScreen нужно использовать методы Navigator.push() и Navigator.pushNamed(), которые могут возвращать значения.
Метод pushNamed() возвращает Future<T>, где T — это тип данных, который будет возвращен при вызове Navigator.pop() со второго экрана.
Нужно будет написать примерно такое
ElevatedButton(
onPressed: () async {
final result = await Navigator.pushNamed(
context,
FirstScreen.routeName,
arguments: UserProfile(name: textController.text),
);
}
),
Что такое await и async и зачем он нужен?
await — это часть асинхронного программирования в Dart. Он используется для ожидания завершения асинхронных операций, которые возвращают Future. Работает обычно в паре с методом async (помечаем функцию которая будет работать асинхронно)
Здесь код делает следующее:
- Открывает экран
FirstScreen - Приостанавливает выполнение текущей функции до тех пор, пока пользователь не вернётся с экрана
FirstScreen(вызоветNavigator.pop()) - Когда пользователь возвращается, в переменную
resultсохраняется значение, переданное вNavigator.pop()
Без await код продолжит выполняться сразу, не дожидаясь возврата пользователя, и вы не сможете сразу получить результат.
- Не забываем создать переменную состояния
String? resultMessageу неё тип данных опциональный потому что неизвестно заранее какой тип данных вернёт методNavigator.pushNamedэто будет в будущем илиnullилиString - Функция обработчик нажатия теперь
asyncпотому что внутри используетсяawait - Не забываем обновить состояние
resultMessageчерезsetState - Нужно вывести возвращаемый результат, обязательно делаем проверку на
null
Файл main_screen.dart
import 'package:flutter/material.dart';
import 'package:flutter_navigation/screens/first_screen.dart';
import 'package:flutter_navigation/screens/user.dart';
class MainScreen extends StatefulWidget {
static const routeName = '/main';
const MainScreen({super.key});
@override
State<MainScreen> createState() => _MainScreenState();
}
class _MainScreenState extends State<MainScreen> {
TextEditingController textController = TextEditingController();
String? resultMessage; // Добавляем переменную для хранения результата
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(title: const Text('Главный экран'), centerTitle: true),
backgroundColor: Colors.white,
body: SizedBox(
width: double.infinity,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Padding(
padding: const EdgeInsets.all(24.0),
child: TextField(
controller: textController,
decoration: const InputDecoration(
border: OutlineInputBorder(),
labelText: 'Введите имя',
),
),
),
// Показываем результат, если он есть
if (resultMessage != null)
Padding(
padding: const EdgeInsets.all(16.0),
child: Text(
resultMessage ?? "",
style: TextStyle(
fontSize: 16,
fontWeight: FontWeight.bold,
color: Colors.green,
),
),
),
ElevatedButton(
onPressed: () async {
// Добавляем await и обрабатываем результат
final result = await Navigator.pushNamed(
context,
FirstScreen.routeName,
arguments: UserProfile(name: textController.text),
);
// Обновляем состояние с полученным результатом
if (result != null) {
setState(() {
resultMessage = result as String;
});
}
},
child: const Text("Открыть FirstScreen"),
),
],
),
),
);
}
}
/